package com.ja.check.data;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONObject;
import org.springframework.web.context.ContextLoader;

import com.alibaba.druid.util.StringUtils;
import com.ja.check.action.CheckOrder;
import com.ja.domain.Data;
import com.ja.sevice.ICpDataAPIService;
import com.ja.sevice.IDataService;
import com.ja.util.DateUtil;
import com.ja.util.JsoupUtil;

/**
 * @DESC: 爬取彩票数据的工具类(依赖C6网)
 * @AUTH: qhzh
 * @DATE: 2018年8月14日 上午11:52:12
 */
public class CpData {

	private IDataService dataService = (IDataService) ContextLoader.getCurrentWebApplicationContext()
			.getBean("dataService");

	private ICpDataAPIService apiService = (ICpDataAPIService) ContextLoader.getCurrentWebApplicationContext()
			.getBean("apiService");
	
	private static Logger logger = (Logger) LogManager.getLogger(CpData.class);
	
	/** 爬取C6网站最后一次开奖数据的URL */
	public static final String URL_C6_LASTOPEN = "http://www.5555c6.com/api/v1/result/service/mobile/results/lastOpen";

	/** 爬取C6网站最新一期数据的URL */
	public static final String URL_C6_CURRENT = "http://www.5555c6.com/api/v1/result/service/mobile/results/current";

	/**19个彩种*/
	public static String[] cnames = { "ah11x5", "ahk3", "cqkl10f", "cqssc", "xjssc", "gd11x5", "gdkl10f",
			"gxk3", "jsk3", "jx11x5", "sd11x5", "sh11x5", "shssl", "tjssc", "xyft", "bjk3", "bjpk10", "fc3d",
			"pl3" ,"bj28"};

	/**
	 * key为彩种名称，value为与此彩种对应没爬到数据的最新一期期号。
	 * 使用：每次爬到数据后先根据彩种名称查询此map中的value，如果期数一致则更新数据库，并将下期期号更新到value中
	 */
	public static Map<String, String> isShotFlags = Collections.synchronizedMap(new HashMap<String, String>());

	
	public void cp() {
		while (true) {
			try {
				//crawlAndSaveCpData();
				Thread.sleep(6000000);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}
	/**
	 * 从C6网爬取彩票数据
	 * 
	 * @return 返回爬到的彩票数据集合
	 */
	public List<Data> crawlCpDataFromC6() {
		List<Data> dataList = new ArrayList<>();
		String body = JsoupUtil.getJsonStrUseAgent(URL_C6_LASTOPEN, 3000);
		if (StringUtils.isEmpty(body) || !body.startsWith("[")) {
			return dataList;
		}
		JSONArray arr = new JSONArray(body);
		for (int i = 0; i < arr.length(); i++) {
			JSONObject obj = arr.getJSONObject(i);
			if (obj.has("gameUniqueId") && obj.has("openStatus") && obj.getBoolean("openStatus")) {
				Data data = new Data();
				String gameUniqueId = obj.getString("gameUniqueId");
				if (!"HF_LFPK10".equals(gameUniqueId) && !"HF_FFPK10".equals(gameUniqueId)
						&& !"HF_FFSSC".equals(gameUniqueId) && !"HF_LF28".equals(gameUniqueId)
						/*&& !"HF_BJ28".equals(gameUniqueId) */&& !"MARK_SIX".equals(gameUniqueId)
						&& !"QXC".equals(gameUniqueId) && !"HF_LFKLPK".equals(gameUniqueId)
						&& !"HF_JSMS".equals(gameUniqueId) && !"HF_LFK3".equals(gameUniqueId)
						&& !"HF_FFK3".equals(gameUniqueId) && !"HF_LFSSC".equals(gameUniqueId)
						&& !"HF_XYSM".equals(gameUniqueId)
						&& !"HF_JLK3".equals(gameUniqueId) && !"HF_FJD11".equals(gameUniqueId)&& !"HF_JS3D".equals(gameUniqueId) && !"HF_HBK3".equals(gameUniqueId)) {
					String cname = convertC6Cname(gameUniqueId);
					if(!cname.equals("名称转换异常")) {
						data.setCname(cname);
						if (obj.has("uniqueIssueNumber")) {
							data.setPeriod(obj.get("uniqueIssueNumber").toString());
						}
						if (obj.has("openCode")) {
							data.setLotternumber(obj.getString("openCode") + ",");
						}
						data.setLottertime(DateUtil.getCurrTime());
						dataList.add(data);
					}
					/*
					 * 下期开奖时间-初始化的时候已经计算出并赋值，不用爬取 if(obj.has("nextOfficialOpenTime")) {
					 * data.setNextStopOrderTimeEpoch(obj.getString("nextOfficialOpenTime").
					 * replaceFirst("T", " ").substring(0, 19)); }
					 */
				}
			}
		}
		return dataList;
	}

	/**
	 * 从彩票控的API爬取彩票数据
	 * 
	 * @return 返回爬到的彩票数据集合
	 */
	public List<Data> crawlCpDataFromCPK() {
		List<Data> dataList = new ArrayList<>();
		String name = null;
		String url = null;
		
		List<String> urls = apiService.findValidApiUrls();
		/*
		String[] urls = {"http://api.caipiaokong.cn/lottery/?name=ahsyxw&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=ahks&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=bjks&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=bjpks&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=cqxync&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=cqssc&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=sd&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=gdsyxw&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=gdklsf&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=gxks&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=jsks&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=jxsyxw&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=sdsyydj&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=shsyxw&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=shssl&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=tjssc&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=xjssc&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863",
				"http://api.caipiaokong.cn/lottery/?name=xyft&format=json&uid=1022056&token=44873288b8c4630316861b3c75260dc073d56863"};
		*/
		for (int i=0;i<urls.size();i++) {
			url = urls.get(i);
			name = url.substring(url.indexOf("name=")+5, url.indexOf("&"));
			url += "&num=1"; 
			String jsonStr = JsoupUtil.getJsonStrUseAgent(url,3000);
			if (StringUtils.isEmpty(jsonStr) || jsonStr.contains("status")) {
				continue;
			}
			JSONObject obj = new JSONObject(jsonStr);
			Iterator<String> iterator = obj.keys();
			String peroid = null;
			String code = null;
			if (iterator.hasNext()) {
				peroid = iterator.next();
				code = obj.getJSONObject(peroid).getString("number") + ",";
			}
			if (StringUtils.isEmpty(peroid)) {
				continue;
			}
			Data data = new Data();
			String cname = convertCPKCname(name);
			if(!cname.equals("名称转换异常")) {
				data.setCname(cname);
				data.setPeriod(formatPeriodOfCPK(cname,peroid));
				data.setLotternumber(code);
				data.setLottertime(DateUtil.getCurrTime());
				dataList.add(data);
			}
		}
		return dataList;
	}

	/**
	 * 将爬到的彩票数据持久化入数据库
	 */
	public void crawlAndSaveCpData() {
		// 遍历彩票数据集合，如果数据库中有相应记录则忽略，如果没有则缓存到一个新集合中，遍历完毕后一次性插入数据库
		List<Data> newDatas = /*new ArrayList<>();*/crawlCpDataFromCPK();
		List<Data> newDatasC6 = crawlCpDataFromC6();
		for(int i=0;i<newDatasC6.size();i++) {
			Data c6Data = newDatasC6.get(i);
			boolean has = false;
			for(int j=0;j<newDatas.size();j++) {
				Data cpkData = newDatas.get(j);
				if(c6Data.equals(cpkData)) {
					has = true;
					break;
				}
			}
			if(!has) {
				newDatas.add(c6Data);
			}
		}
		if (newDatas.size() == 0) {
			return;
		}
		//System.out.println("CpData.crawlAndSaveCpData()--合并后的爬取数据为："+newDatas.size()+"\n"+newDatas);
		List<Data> updateDatas = new ArrayList<>();
		for (int i=0;i<newDatas.size();i++) {
			Data newData = newDatas.get(i); 
			if(!isShotFlags.containsKey(newData.getCname()) || newData.getPeriod().equals(isShotFlags.get(newData.getCname()))) {
				updateDatas.add(newData);
			}
		}
		// 批量更新数据
		if (!updateDatas.isEmpty()) {
			//System.out.println("["+DateUtil.getCurrTime()+"]"+"-----待更新的彩票数据量为：" + updateDatas.size());
			for (Data data : updateDatas) {
				String cname = data.getCname();
				//System.err.println(cname);
				//System.out.println("查询的当前数据为："+data);
				//System.out.println(cname+"-------------老赵打印的-------------------"+data.getPeriod());
				Data entity = dataService.findDataByNameAndPeriod(cname, data.getPeriod());
				/*System.out.println(entity+"entity的值");*/
				if(entity == null) {
					System.out.println(cname+"-------------这个彩种的在一期数据库为null请及时处理负责将影响到开奖结果-------------------"+data.getPeriod());
				}
			}
			//System.out.println(updateDatas+"----------------爬到并且更新的数据");
			dataService.updateByBatch(updateDatas);
			// 调用开奖的接口: 1、爬到开奖号码就调用；
			openLotteries(updateDatas);
		}
	}
	/**
	 * 格式化彩票控的期号
	 * @param cname
	 * @param cpkPeriod
	 * @return
	 */
	private String formatPeriodOfCPK(String cname, String cpkPeriod) {
		String period = cpkPeriod;
		StringBuilder temp = null;
		switch (cname) {
		case "ah11x5":
		case "cqkl10f":
		case "gd11x5":
		case "gxk3":
		case "jsk3":
			period = "20"+ cpkPeriod;
			break;
		case "xjssc":
		case "gdkl10f":
			temp = new StringBuilder(cpkPeriod);
			temp.insert( temp.length()-2,"0");
			period = temp.toString();
			break;
		default:
			break;
		}
		return period;
	}

	/**
	 * 给map排序，key的顺序为：{ "ah11x5", "ahk3", "cqkl10f", "cqssc", "xjssc", "fj11x5",
	 * "gd11x5", "gdkl10f", "gxk3", "jlk3", "jsk3", "jx11x5", "sd11x5", "sh11x5",
	 * "shssl", "tjssc", "xyft", "bjk3", "bjpk10", "fc3d", "pl3" }
	 * 
	 * @param dataMap
	 */
	private Map<String, String> sortCurrMap(Map<String, String> dataMap) {
		if(dataMap.isEmpty()) {
			return dataMap;
		}
		Map<String, String> tempMap = new HashMap<>();
		for (int i = 0; i < cnames.length-1; i++) {
			for (String key : dataMap.keySet()) {
				if (cnames[i].equals(key)) {
					tempMap.put(key, dataMap.get(key));
					break;
				}
			}
		}
		return tempMap;
	}

	/**
	 * 从C6网爬取各彩种最新一期的期数(不包含福建11选5和吉林快3共19个彩种)
	 * 
	 * @return
	 */
	public Map<String, String> getCurrMapFromC6() {
		Map<String, String> dataMap = new HashMap<>();
		String jsonStr = JsoupUtil.getJsonStrUseAgent(URL_C6_CURRENT, 3000);
		while (StringUtils.isEmpty(jsonStr) || !jsonStr.startsWith("[")) {
			try {
				Thread.sleep(1000);
				jsonStr = JsoupUtil.getJsonStrUseAgent(URL_C6_CURRENT, 3000);
			} catch (InterruptedException e) {
				//System.out.println("[wch2-------------------" + DateUtil.getCurrTime() + "]" + "CpData.getCurrMap()-----" + e.getMessage());
			}
		}
		JSONArray arr = new JSONArray(jsonStr);
		for (int i = 0; i < arr.length(); i++) {
			JSONObject obj = arr.getJSONObject(i);
			if (obj.has("gameUniqueId") && obj.has("openStatus") && !obj.getBoolean("openStatus")) {
				String gameUniqueId = obj.getString("gameUniqueId");
				String uniqueIssueNumber = "-1";
				if (!"HF_LFPK10".equals(gameUniqueId) && !"HF_FFPK10".equals(gameUniqueId)
						&& !"HF_FFSSC".equals(gameUniqueId) && !"HF_LF28".equals(gameUniqueId)
						/*&& !"HF_BJ28".equals(gameUniqueId)*/ && !"MARK_SIX".equals(gameUniqueId)
						&& !"QXC".equals(gameUniqueId) && !"HF_LFKLPK".equals(gameUniqueId)
						&& !"HF_JSMS".equals(gameUniqueId) && !"HF_LFK3".equals(gameUniqueId)
						&& !"HF_FFK3".equals(gameUniqueId) && !"HF_LFSSC".equals(gameUniqueId)
						&& !"HF_XYSM".equals(gameUniqueId)
						&& !"HF_JLK3".equals(gameUniqueId) && !"HF_FJD11".equals(gameUniqueId)) {
					if (obj.has("uniqueIssueNumber")) {
						uniqueIssueNumber = obj.get("uniqueIssueNumber").toString();
					}
					dataMap.put(convertC6Cname(gameUniqueId), uniqueIssueNumber);
				}
			}
		}
		//System.out.println("[wch1------------------" + DateUtil.getCurrTime() + "]" + "CpData.getCurrMapFromC6()-----爬到当前期数集合大小为：" + dataMap.size());
		return sortCurrMap(dataMap);
	}

	/**
	 * 调用开奖的接口
	 * 
	 * @param updateDatas
	 */
	private void openLotteries(List<Data> updateDatas) {
		logger.info("老赵------"+updateDatas +"openLotteries");
		CheckOrder order = new CheckOrder();
		for (Data data : updateDatas) {
			order.checkLotters(data);
		}
	}

	/**
	 * 彩票控网站彩种名称转换：将爬到的名称转换为本系统自定义的（拼音的小写字母加数字） { "ah11x5", "ahk3", "cqkl10f", "cqssc",
	 * "xjssc", "fj11x5", "gd11x5", "gdkl10f", "gxk3", "jlk3", "jsk3", "jx11x5",
	 * "sd11x5", "sh11x5", "shssl", "tjssc", "xyft", "bjk3", "bjpk10", "fc3d", "pl3"
	 * };
	 * 
	 * @param cnameOfCPK
	 * @return
	 */
	public String convertCPKCname(String cnameOfCPK) {
		switch (cnameOfCPK) {
		case "ahsyxw":
			return "ah11x5";
		case "ahks":
			return "ahk3";
		case "cqxync":
			return "cqkl10f";
		case "cqssc":
			return "cqssc";
		case "xjssc":
			return "xjssc";
		case "fjsyxw":
			return "fj11x5";
		case "gdsyxw":
			return "gd11x5";
		case "gdklsf":
			return "gdkl10f";
		case "gxks":
			return "gxk3";
		case "jlks":
			return "jlk3";
		case "jsks":
			return "jsk3";
		case "jxsyxw":
			return "jx11x5";
		case "sdsyydj":
			return "sd11x5";
		case "shsyxw":
			return "sh11x5";
		case "shssl":
			return "shssl";
		case "tjssc":
			return "tjssc";
		case "xyft":
			return "xyft";
		case "bjks":
			return "bjk3";
		case "bjpks":
			return "bjpk10";
		case "sd":
			return "fc3d";
		case "pls":
			return "pl3";

		default:
			//System.out.println("[" + DateUtil.getCurrTime() + "]" + "CpData.convertCname()-----彩票名称转换异常..."+cnameOfCPK);
			return "名称转换异常";
		}
	}
	
	/**
	 * 开彩网网站彩种名称转换：将爬到的名称转换为自定义的（拼音的小写字母加数字） { "ah11x5", "ahk3", "cqkl10f", "cqssc",
	 * "xjssc", "fj11x5", "gd11x5", "gdkl10f", "gxk3", "jlk3", "jsk3", "jx11x5",
	 * "sd11x5", "sh11x5", "shssl", "tjssc", "xyft", "bjk3", "bjpk10", "fc3d", "pl3"
	 * };
	 * 
	 * @param cnameOfKCW
	 * @return
	 */
	public String convertKCWCname(String cnameOfKCW) {
		switch (cnameOfKCW) {
		case "cqklsf":
			return "cqkl10f";
		case "gdklsf":
			return "gdkl10f";
			
		default:
			return cnameOfKCW;
		}
	}

	/**
	 * C6网站彩种名称转换：将爬到的名称转换为自定义的（拼音的小写字母加数字）
	 * 
	 * @param cnameOfC6
	 * @return
	 */
	private String convertC6Cname(String cnameOfC6) {
		switch (cnameOfC6) {
		case "HF_FFK3":
			return "ffk3";
		case "HF_LFK3":
			return "2fk3";
		case "HF_JSMS":
			return "jslhc";
		case "HF_LFKLPK":
			return "xypk";
		case "HF_JLK3":
			return "jlk3";
		case "HF_BJK3":
			return "bjk3";
		case "HF_JSK3":
			return "jsk3";
		case "HF_GXK3":
			return "gxk3";
		case "HF_AHK3":
			return "ahk3";
		case "QXC":
			return "qxc";
		case "X3D":
			return "fc3d";
		case "PL3":
			return "pl3";
		case "HF_SHSSL":
			return "shssl";
		case "MARK_SIX":
			return "xglhc";
		case "HF_FJD11":
			return "fj11x5";
		case "HF_SHD11":
			return "sh11x5";
		case "HF_SDD11":
			return "sd11x5";
		case "HF_JXD11":
			return "jx11x5";
		case "HF_GDD11":
			return "gd11x5";
		case "HF_AHD11":
			return "ah11x5";
		case "HF_CQKL10F":
			return "cqkl10f";
		case "HF_GDKL10F":
			return "gdkl10f";
		case "HF_LF28":
			return "xy28";
		case "HF_BJ28":
			return "bj28";
		case "HF_XJSSC":
			return "xjssc";
		case "HF_TJSSC":
			return "tjssc";
		case "HF_FFSSC":
			return "ffssc";
		case "HF_LFSSC":
			return "efssc";
		case "HF_CQSSC":
			return "cqssc";
		case "HF_XYSM":
			return "xysm";
		case "HF_XYFT":
			return "xyft";
		case "HF_FFPK10":
			return "ffpk10";
		case "HF_LFPK10":
			return "efpk10";
		case "HF_BJPK10":
			return "bjpk10";

		default:
			//System.out.println("[" + DateUtil.getCurrTime() + "]" + "convertC6Cname CpData.convertCname()-----彩票名称转换异常..."+cnameOfC6);
			return "名称转换异常";
		}
	}

	/**
	 * 剔除字符串中的汉字
	 * 
	 * @param openCode
	 * @return
	 */
	public String delChinese(String openCode) {
		return openCode.replaceAll("\\D", "");
	}

	/**
	 * 格式化开奖号码
	 * 
	 * @param openCode
	 *            开奖号码
	 * @param isOneBit
	 *            开奖号码为一位数字还是两位数字
	 * @return
	 */
	public String formatOpenCode(String openCode, boolean isOneBit) {
		char[] chars = openCode.toCharArray();
		StringBuilder sb = new StringBuilder();
		for (int i = 0; i < chars.length; i++) {
			if (isOneBit) {
				sb.append(chars[i] + ",");
			} else {
				sb.append(chars[i] + "" + chars[++i] + ",");
			}
		}
		return sb.toString();
	}

	public static void main(String[] args) {
		StringBuilder temp = new StringBuilder("20180090644");
		temp.insert( temp.length()-2,"0");
		//System.out.println("wch1------------------"+temp);
		/*
		String jsonStr = "{\"id\":\"3\",\"name\":\"bob\",\"pass\":\"123\"}";
		System.out.println(jsonStr);
		JSONObject jsonObj = new JSONObject(jsonStr);
		System.out.println(jsonObj.get("name"));
		String arrStr = "{\"2018090545\":{\"number\":\"1,4,6,9,4\",\"dateline\":\"2018-09-05 17:30:17\"},\"2018090544\":{\"number\":\"5,3,6,1,1\",\"dateline\":\"2018-09-05 17:20:10\"},\"2018090543\":{\"number\":\"8,7,9,9,8\",\"dateline\":\"2018-09-05 17:10:14\"},\"2018090542\":{\"number\":\"7,7,2,6,9\",\"dateline\":\"2018-09-05 17:00:14\"},\"2018090541\":{\"number\":\"3,5,7,0,8\",\"dateline\":\"2018-09-05 16:50:19\"},\"2018090540\":{\"number\":\"3,3,8,2,7\",\"dateline\":\"2018-09-05 16:40:20\"},\"2018090539\":{\"number\":\"4,9,9,2,4\",\"dateline\":\"2018-09-05 16:30:12\"},\"2018090538\":{\"number\":\"5,5,4,9,8\",\"dateline\":\"2018-09-05 16:20:18\"},\"2018090537\":{\"number\":\"3,8,1,7,4\",\"dateline\":\"2018-09-05 16:10:08\"},\"2018090536\":{\"number\":\"9,7,6,4,7\",\"dateline\":\"2018-09-05 16:00:16\"}}";
		System.out.println(arrStr);
		JSONObject jsonArr = new JSONObject(arrStr);
		System.out.println(jsonArr.getJSONObject("2018090544").toString());
		System.out.println(jsonArr.getJSONObject("2018090544").getString("number"));
		 */
		//System.out.println("--------------over----------------");
	}

}
